package com.martin.lib_base.ktx

import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ViewModel
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.viewModelScope
import com.martin.lib_base.bean.common.BaseResponse
import com.martin.lib_base.model.PageModel
import com.martin.lib_base.utils.ExceptionUtil
import dev.DevUtils
import dev.utils.common.ReflectUtils
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody

/**
 * @author：孟凡华
 * @date：2022/11/21
 * @desc：网络请求封装
 */

/**
 * 请求回调类
 */
class ResultBuilder<T> {
    /**
     * 请求成功
     */
    var onSuccess: (data: BaseResponse<T>) -> Unit = {}

    /**
     * 请求失败
     */
    var onFailed: (code: Int, message: String) -> Unit = { _, message -> showToast(message) }

    /**
     * 请求完成
     */
    var onComplete: () -> Unit = {}
}

/**
 * 构建请求参数
 */
fun buildRequest(data: Any? = null): RequestBody {
    return data.toJson(false)
        .toRequestBody("application/json; charset=utf-8".toMediaTypeOrNull())
}

/**
 * 分析结果,执行回调
 */
private suspend fun <T> parseResultAndCallback(
    response: BaseResponse<T>,
    listener: ResultBuilder<T>
) {
    withContext(Dispatchers.Main) {
        when (response.code) {
            //请求正常
            200, 0 -> {
                listener.onSuccess(response)
            }

            401 -> {
                ReflectUtils.reflect("${DevUtils.getContext().packageName}.helper.UserHelper")
                    .field("INSTANCE")
                    .method("logout")
            }
            //其他异常
            else -> {
                listener.onFailed(response.code, response.msg)
            }
        }
    }
}

/**
 * 启动请求并收集数据
 * 有loading加载框
 */
fun <T> Any.launchLoadingCollect(
    block: suspend () -> BaseResponse<T>,
    resultBuilder: ResultBuilder<T>.() -> Unit
) {
    val listener = ResultBuilder<T>().also(resultBuilder)
    flow {
        emit(block())
    }
        .flowOn(Dispatchers.IO)
        .onStart {
//            showLoading()
        }
        .onEach {
            parseResultAndCallback(it, listener)
        }
        .catch {
            listener.onFailed(-1, ExceptionUtil.catchException(it))
        }
        .onCompletion {
//            dismissLoading()
            listener.onComplete()
        }
        .flowOn(Dispatchers.Main)
        .launchIn(
            when (this) {
                is LifecycleOwner -> this.lifecycleScope
                is ViewModel -> viewModelScope
                else -> GlobalScope
            }
        )
}

/**
 * 启动请求并收集数据
 * 没有loading加载框
 */
fun <T> Any.launchCollect(
    block: suspend () -> BaseResponse<T>,
    resultBuilder: ResultBuilder<T>.() -> Unit
) {
    val that = this
    val listener = ResultBuilder<T>().also(resultBuilder)
    flow {
        emit(block())
    }
        .flowOn(Dispatchers.IO)
        .onEach {
            parseResultAndCallback(it, listener)
        }
        .catch {
            listener.onFailed(-1, ExceptionUtil.catchException(it))
        }
        .onCompletion {
            listener.onComplete()
            // 分页工具,在访问结束后,关闭刷新状态
            if (that is PageModel) {
                that.finishLoading()
            }
        }
        .flowOn(Dispatchers.Main)
        .launchIn(
            when (this) {
                is LifecycleOwner -> this.lifecycleScope
                is ViewModel -> viewModelScope
                else -> GlobalScope
            }
        )
}
